﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Metadata.Edm;
using System.Data.Entity.Infrastructure;

namespace FlowBasis.EntityFramework
{
    public class EntityFrameworkMetadataService
    {
        private Func<DbContext> dbContextFactory;
        private List<Type> entityTypes;
        private Dictionary<string, EntitySet> elementTypeNameToEntitySetMap;

        public EntityFrameworkMetadataService(Func<DbContext> dbContextFactory, IEnumerable<Type> entityTypes)
        {
            this.dbContextFactory = dbContextFactory;
            this.entityTypes = entityTypes.ToList();

            this.Refresh();
        }

        private void Refresh()
        {
            using (var dbContext = this.dbContextFactory())
            {
                var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;

                var entityContainer = objectContext.MetadataWorkspace.GetEntityContainer(
                    objectContext.DefaultContainerName,
                    System.Data.Metadata.Edm.DataSpace.CSpace);

                var newElementTypeNameToEntitySetMap = new Dictionary<string, EntitySet>();

                foreach (var baseEntitySet in entityContainer.BaseEntitySets)
                {
                    if (baseEntitySet.BuiltInTypeKind == BuiltInTypeKind.EntitySet)
                    {
                        newElementTypeNameToEntitySetMap[baseEntitySet.ElementType.Name] = (EntitySet)baseEntitySet;                        
                    }
                }

                this.elementTypeNameToEntitySetMap = newElementTypeNameToEntitySetMap;                
            }
        }

        public EntitySet TryGetEntitySetForClrType(Type type)
        {
            EntitySet entitySet;
            if (this.elementTypeNameToEntitySetMap.TryGetValue(type.Name, out entitySet))
                return entitySet;
            else
                return null;
        }

        public EntityType TryGetEntityTypeForClrType(Type type)
        {
            var entitySet = this.TryGetEntitySetForClrType(type);
            if (entitySet != null)
                return entitySet.ElementType;
            else
                return null;
        }
    }
}
